#include "stdafx.h"
#include "ShaderVariable.h"

namespace Reign
{namespace Video
{namespace D3D10
{
	#pragma region
	string^ ShaderVariable::Name::get() {return name;}
	#pragma endregion

	#pragma region Constructors
	ShaderVariable::ShaderVariable(char* vertexBytes, char* pixelBytes, int vertexOffset, int pixelOffset, string^ name)
	{
		this->vertexBytes = vertexBytes;
		this->pixelBytes = pixelBytes;

		this->vertexOffset = vertexOffset;
		this->pixelOffset = pixelOffset;

		this->name = name;
	}
	#pragma endregion

	#pragma region Methods
	void ShaderVariable::copy(array<float>^ values, int offset, int count)
	{
		pin_ptr<void> ptr = &values[offset];
		char* valueData = ((char*)(void*)ptr);
		if (vertexOffset != -1)
		{
			char* data = vertexBytes + vertexOffset;
			int valueOffset = 0, dataOffset = 0;
			for (int i = 0; i != count; ++i)
			{
				memcpy(data + dataOffset, valueData + valueOffset, sizeof(float));
				valueOffset += sizeof(float);
				dataOffset += sizeof(Vector4);
			}
		}

		if (pixelOffset != -1)
		{
			char* data = pixelBytes + pixelOffset;
			int valueOffset = 0, dataOffset = 0;
			for (int i = 0; i != count; ++i)
			{
				memcpy(data + dataOffset, valueData + valueOffset, sizeof(float));
				valueOffset += sizeof(float);
				dataOffset += sizeof(Vector4);
			}
		}
	}

	void ShaderVariable::copy(array<Vector2>^ values, int offset, int count)
	{
		pin_ptr<void> ptr = &values[offset];
		char* valueData = ((char*)(void*)ptr);
		if (vertexOffset != -1)
		{
			char* data = vertexBytes + vertexOffset;
			int valueOffset = 0, dataOffset = 0;
			for (int i = 0; i != count; ++i)
			{
				memcpy(data + dataOffset, valueData + valueOffset, sizeof(Vector2));
				valueOffset += sizeof(Vector2);
				dataOffset += sizeof(Vector4);
			}
		}

		if (pixelOffset != -1)
		{
			char* data = pixelBytes + pixelOffset;
			int valueOffset = 0, dataOffset = 0;
			for (int i = 0; i != count; ++i)
			{
				memcpy(data + dataOffset, valueData + valueOffset, sizeof(Vector2));
				valueOffset += sizeof(Vector2);
				dataOffset += sizeof(Vector4);
			}
		}
	}

	void ShaderVariable::copy(array<Vector3>^ values, int offset, int count)
	{
		pin_ptr<void> ptr = &values[offset];
		char* valueData = ((char*)(void*)ptr);
		if (vertexOffset != -1)
		{
			char* data = vertexBytes + vertexOffset;
			int valueOffset = 0, dataOffset = 0;
			for (int i = 0; i != count; ++i)
			{
				memcpy(data + dataOffset, valueData + valueOffset, sizeof(Vector3));
				valueOffset += sizeof(Vector3);
				dataOffset += sizeof(Vector4);
			}
		}

		if (pixelOffset != -1)
		{
			char* data = pixelBytes + pixelOffset;
			int valueOffset = 0, dataOffset = 0;
			for (int i = 0; i != count; ++i)
			{
				memcpy(data + dataOffset, valueData + valueOffset, sizeof(Vector3));
				valueOffset += sizeof(Vector3);
				dataOffset += sizeof(Vector4);
			}
		}
	}

	void ShaderVariable::Set(float value)
	{
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, &value, sizeof(float));
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, &value, sizeof(float));
	}

	void ShaderVariable::Set(float x, float y)
	{
		if (vertexOffset != -1)
		{
			char* data = vertexBytes + vertexOffset;
			memcpy(data, &x, sizeof(float));
			memcpy(data + sizeof(float), &y, sizeof(float));
		}

		if (pixelOffset != -1)
		{
			char* data = pixelBytes + pixelOffset;
			memcpy(data, &x, sizeof(float));
			memcpy(data + sizeof(float), &y, sizeof(float));
		}
	}

	void ShaderVariable::Set(float x, float y, float z)
	{
		if (vertexOffset != -1)
		{
			char* data = vertexBytes + vertexOffset;
			memcpy(data, &x, sizeof(float));
			memcpy(data + sizeof(float), &y, sizeof(float));
			memcpy(data + sizeof(float)*2, &z, sizeof(float));
		}

		if (pixelOffset != -1)
		{
			char* data = pixelBytes + pixelOffset;
			memcpy(data, &x, sizeof(float));
			memcpy(data + sizeof(float), &y, sizeof(float));
			memcpy(data + sizeof(float)*2, &z, sizeof(float));
		}
	}

	void ShaderVariable::Set(float x, float y, float z, float w)
	{
		if (vertexOffset != -1)
		{
			char* data = vertexBytes + vertexOffset;
			memcpy(data, &x, sizeof(float));
			memcpy(data + sizeof(float), &y, sizeof(float));
			memcpy(data + sizeof(float)*2, &z, sizeof(float));
			memcpy(data + sizeof(float)*3, &w, sizeof(float));
		}

		if (pixelOffset != -1)
		{
			char* data = pixelBytes + pixelOffset;
			memcpy(data, &x, sizeof(float));
			memcpy(data + sizeof(float), &y, sizeof(float));
			memcpy(data + sizeof(float)*2, &z, sizeof(float));
			memcpy(data + sizeof(float)*3, &w, sizeof(float));
		}
	}

	void ShaderVariable::Set(Vector2 value)
	{
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, &value, sizeof(Vector2));
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, &value, sizeof(Vector2));
	}

	void ShaderVariable::Set(Vector3 value)
	{
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, &value, sizeof(Vector3));
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, &value, sizeof(Vector3));
	}

	void ShaderVariable::Set(Vector4 value)
	{
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, &value, sizeof(Vector4));
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, &value, sizeof(Vector4));
	}

	void ShaderVariable::Set(Matrix2 value)
	{
		pin_ptr<void> ptr = &value;
		char* valueData = (char*)(void*)ptr;
		if (vertexOffset != -1)
		{
			memcpy(vertexBytes + vertexOffset, valueData, sizeof(Vector2));
			memcpy(vertexBytes + vertexOffset + sizeof(Vector4), valueData + sizeof(Vector2), sizeof(Vector2));
			memcpy(vertexBytes + vertexOffset + (sizeof(Vector4) * 2), valueData + (sizeof(Vector2) * 2), sizeof(Vector2));
		}

		if (pixelOffset != -1)
		{
			memcpy(pixelBytes + pixelOffset, valueData, sizeof(Vector2));
			memcpy(pixelBytes + pixelOffset + sizeof(Vector4), valueData + sizeof(Vector2), sizeof(Vector2));
			memcpy(pixelBytes + pixelOffset + (sizeof(Vector4) * 2), valueData + (sizeof(Vector2) * 2), sizeof(Vector2));
		}
	}

	void ShaderVariable::Set(Matrix3 value)
	{
		pin_ptr<void> ptr = &value;
		char* valueData = (char*)(void*)ptr;
		if (vertexOffset != -1)
		{
			memcpy(vertexBytes + vertexOffset, valueData, sizeof(Vector3));
			memcpy(vertexBytes + vertexOffset + sizeof(Vector4), valueData + sizeof(Vector3), sizeof(Vector3));
			memcpy(vertexBytes + vertexOffset + (sizeof(Vector4) * 2), valueData + (sizeof(Vector3) * 2), sizeof(Vector3));
		}

		if (pixelOffset != -1)
		{
			memcpy(pixelBytes + pixelOffset, valueData, sizeof(Vector3));
			memcpy(pixelBytes + pixelOffset + sizeof(Vector4), valueData + sizeof(Vector3), sizeof(Vector3));
			memcpy(pixelBytes + pixelOffset + (sizeof(Vector4) * 2), valueData + (sizeof(Vector3) * 2), sizeof(Vector3));
		}
	}

	void ShaderVariable::Set(Matrix4 value)
	{
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, &value, sizeof(Matrix4));
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, &value, sizeof(Matrix4));
	}

	void ShaderVariable::Set(array<float>^ values)
	{
		copy(values, 0, values->Length);
	}

	void ShaderVariable::Set(array<Vector2>^ values)
	{
		copy(values, 0, values->Length);
	}

	void ShaderVariable::Set(array<Vector3>^ values)
	{
		copy(values, 0, values->Length);
	}

	void ShaderVariable::Set(array<Vector4>^ values)
	{
		pin_ptr<void> ptr = &values[0];
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, ptr, sizeof(Vector4) * values->Length);
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, ptr, sizeof(Vector4) * values->Length);
	}

	void ShaderVariable::Set(array<Matrix2>^ values)
	{
		throw gcnew NotImplementedException();
	}

	void ShaderVariable::Set(array<Matrix3>^ values)
	{
		throw gcnew NotImplementedException();
	}

	void ShaderVariable::Set(array<Matrix4>^ values)
	{
		pin_ptr<void> ptr = &values[0];
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, ptr, sizeof(Matrix4) * values->Length);
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, ptr, sizeof(Matrix4) * values->Length);
	}

	void ShaderVariable::Set(array<float>^ values, int count)
	{
		copy(values, 0, count);
	}

	void ShaderVariable::Set(array<Vector2>^ values, int count)
	{
		copy(values, 0, count);
	}

	void ShaderVariable::Set(array<Vector3>^ values, int count)
	{
		copy(values, 0, count);
	}

	void ShaderVariable::Set(array<Vector4>^ values, int count)
	{
		pin_ptr<void> ptr = &values[0];
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, ptr, sizeof(Vector4) * count);
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, ptr, sizeof(Vector4) * count);
	}

	void ShaderVariable::Set(array<Matrix2>^ values, int count)
	{
		throw gcnew NotImplementedException();
	}

	void ShaderVariable::Set(array<Matrix3>^ values, int count)
	{
		throw gcnew NotImplementedException();
	}

	void ShaderVariable::Set(array<Matrix4>^ values, int count)
	{
		pin_ptr<void> ptr = &values[0];
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, ptr, sizeof(Matrix4) * count);
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, ptr, sizeof(Matrix4) * count);
	}

	void ShaderVariable::Set(array<float>^ values, int offset, int count)
	{
		copy(values, offset, count);
	}

	void ShaderVariable::Set(array<Vector2>^ values, int offset, int count)
	{
		copy(values, offset, count);
	}

	void ShaderVariable::Set(array<Vector3>^ values, int offset, int count)
	{
		copy(values, offset, count);
	}

	void ShaderVariable::Set(array<Vector4>^ values, int offset, int count)
	{
		pin_ptr<void> ptr = &values[offset];
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, ptr, sizeof(Vector4) * count);
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, ptr, sizeof(Vector4) * count);
	}

	void ShaderVariable::Set(array<Matrix2>^ values, int offset, int count)
	{
		throw gcnew NotImplementedException();
	}

	void ShaderVariable::Set(array<Matrix3>^ values, int offset, int count)
	{
		throw gcnew NotImplementedException();
	}

	void ShaderVariable::Set(array<Matrix4>^ values, int offset, int count)
	{
		pin_ptr<void> ptr = &values[offset];
		if (vertexOffset != -1) memcpy(vertexBytes + vertexOffset, ptr, sizeof(Matrix4) * count);
		if (pixelOffset != -1) memcpy(pixelBytes + pixelOffset, ptr, sizeof(Matrix4) * count);
	}
	#pragma endregion
}
}
}